package app.gui;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.SpinnerListModel;

import app.Main;
import app.conn.WebDB;

/**
 * Greenhouse configuration and records frame
 * 
 * Contains panels for setting ventilation and watering
 * and chart with recorded data
 * 
 * @author Lukas Vavra
 *
 */
public class ConfigFrame extends JFrame {

	private ConfigModel cnfModel;

	private JCheckBox autoVentCtrl;
	private JCheckBox autoWatCtrl;

	private JLabel tempText = new JLabel("Vnitřní teplota");
	private JLabel humText = new JLabel("Vzdušná vlhkost");

	private JLabel minTPrefix = new JLabel("Minimální: ");
	private JLabel minTPostfix = new JLabel("°C");
	private JTextField minTField;

	private JLabel maxTPrefix = new JLabel("Maximální: ");
	private JLabel maxTPostfix = new JLabel("°C");
	private JTextField maxTField;

	private JLabel minHPrefix = new JLabel("Minimální: ");
	private JLabel minHPostfix = new JLabel("%");
	private JTextField minHField;

	private JLabel maxHPrefix = new JLabel("Maximální: ");
	private JLabel maxHPostfix = new JLabel("%");
	private JTextField maxHField;

	private JLabel soilText = new JLabel("Půdní vlhkost");
	private JLabel minPrefix = new JLabel("Minimální: ");
	private JLabel minPostfix = new JLabel("%");
	private JTextField minField;

	private JLabel maxPrefix = new JLabel("Maximální: ");
	private JLabel maxPostfix = new JLabel("%");
	private JTextField maxField;

	private JTextField recdelayField;
	private JTextField mandelayField;

	private TimeListPanel ventilationTimeListPanel;
	private TimeListPanel wateringTimeListPanel;



	// records diagram, have to be closed with this frame, when exist
	private JDialog recordsDiagram = null;

	/**
	 * Frame constructor
	 * 
	 */
	public ConfigFrame() {
		new ConfigFrame(null);
	}

	public ConfigFrame(ConfigModel model) {
		super("Správa řídící jednotky");

		if(model != null) 
			this.cnfModel = model;
		else 
			this.cnfModel = new ConfigModel();


		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		this.setLayout(new GridBagLayout());

		JPanel controlPanel = new JPanel(new GridLayout(1, 2));
		controlPanel.add(new WateringPanel());
		controlPanel.add(new VentilationPanel());

		JPanel optionPanel = new JPanel(new GridBagLayout());
		optionPanel.setBorder(BorderFactory.createTitledBorder("Nastavení časových intervalů"));
		GridBagConstraints cs = new GridBagConstraints();
		cs.insets = new Insets(10, 10, 10, 10);
		cs.fill = GridBagConstraints.HORIZONTAL;


		cs.gridx = 0;
		cs.gridy = 0;
		cs.gridwidth = 1;
		cs.gridheight = 1;
		optionPanel.add(new JLabel("Interval záznamu dat"), cs);


		recdelayField = new JTextField(10);
		recdelayField.setText(Integer.toString(this.cnfModel.getRecDelay()));
		cs.gridx = 1;
		cs.gridy = 0;
		cs.gridwidth = 1;
		cs.gridheight = 1;
		cs.ipadx = 20;
		optionPanel.add(recdelayField, cs);

		cs.insets = new Insets(10, 10, 10, 30);
		cs.gridx = 2;
		cs.gridy = 0;
		cs.gridwidth = 1;
		cs.gridheight = 1;
		cs.ipadx = 0;
		optionPanel.add(new JLabel("s"), cs);

		cs.insets = new Insets(10, 10, 10, 10);
		cs.gridx = 3;
		cs.gridy = 0;
		cs.gridwidth = 1;
		cs.gridheight = 1;
		optionPanel.add(new JLabel("Prodleva ručního ovládání"), cs);


		mandelayField = new JTextField(10);
		mandelayField.setText(Integer.toString(this.cnfModel.getManDelay()));
		cs.gridx = 4;
		cs.gridy = 0;
		cs.gridwidth = 1;
		cs.gridheight = 1;
		cs.ipadx = 20;
		optionPanel.add(mandelayField, cs);

		cs.gridx = 5;
		cs.gridy = 0;
		cs.gridwidth = 1;
		cs.gridheight = 1;
		cs.ipadx = 0;
		optionPanel.add(new JLabel("s"), cs);

		JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 10, 10));

		JButton recButton = new JButton("Zobrazit záznamy");
		recButton.addActionListener(new ShowRecordsListener());
		buttonPanel.add(recButton);
		if(!this.cnfModel.isRemoteAccess() && MainFrame.getInstance().recFile == null) {
			recButton.setEnabled(false);
		}

		JButton cancelButton = new JButton("Storno");
		cancelButton.addActionListener(new CancelButtonListener());
		buttonPanel.add(cancelButton);

		JButton saveButton = new JButton("Uložit");
		saveButton.addActionListener(new SaveButtonListener());
		buttonPanel.add(saveButton);


		cs.fill = GridBagConstraints.HORIZONTAL;
		cs.gridx = 1;
		cs.gridwidth = GridBagConstraints.REMAINDER;
		cs.gridheight = 1;
		cs.weightx = 1;
		cs.weighty = 1;
		cs.insets = new Insets(0, 10, 0, 10);

		cs.gridy = 0;
		this.add(controlPanel, cs);
		cs.gridy = 1;
		this.add(optionPanel, cs);
		cs.gridy = 2;
		this.add(buttonPanel, cs);

		this.pack();
		this.setSize(new Dimension(800, 600));
		this.setLocationRelativeTo(null);
		this.setVisible(true);
	}

	/**
	 * Save Button Listener
	 * 
	 * @author Lukas Vavra
	 *
	 */
	public class SaveButtonListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent arg0) {
			// ventilation
			if(ventilationTimeListPanel.getData() != null)
				cnfModel.setVentilationData(cnfModel.parseTimesFromList(
						ventilationTimeListPanel.getData(), ConfigModel.VENT_DELAY_STEP));
			if(autoVentCtrl.isSelected()) {
				cnfModel.setAutoVentilation(true);
				cnfModel.setMaxTemp(Integer.parseInt(maxTField.getText()));
				cnfModel.setMinTemp(Integer.parseInt(minTField.getText()));
				cnfModel.setMaxHum(Integer.parseInt(maxHField.getText()));
				cnfModel.setMinHum(Integer.parseInt(minHField.getText()));
			}
			else {
				cnfModel.setAutoVentilation(false);
			}

			// watering
			if(wateringTimeListPanel.getData() != null)
				cnfModel.setWateringData(cnfModel.parseTimesFromList(
						wateringTimeListPanel.getData(), ConfigModel.WAT_DELAY_STEP));			
			if(autoWatCtrl.isSelected()) {
				cnfModel.setAutoWatering(true);
				cnfModel.setMaxSM(Integer.parseInt(maxField.getText()));
				cnfModel.setMinSM(Integer.parseInt(minField.getText()));
			}
			else {
				cnfModel.setAutoWatering(false);
			}


			// delays
			cnfModel.setRecDelay(Integer.parseInt(recdelayField.getText()));
			cnfModel.setManDelay(Integer.parseInt(mandelayField.getText()));

			// save model
			cnfModel.save();

			// close records dialog, if exist
			if(recordsDiagram != null) {
				recordsDiagram.dispose();
			}

			// close frame
			dispose();
		}

	}

	/**
	 * Cancel Button Listener
	 * 
	 * @author Lukas Vavra
	 *
	 */
	public class CancelButtonListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			if(recordsDiagram != null) {
				recordsDiagram.dispose();
			}
			dispose();
		}

	}

	/**
	 * Show Records Button Listener
	 * 
	 * @author Lukas Vavra
	 *
	 */
	public class ShowRecordsListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			if(cnfModel.isRemoteAccess()) {
				try {
					RecordsModel recmod = new RecordsModel();
					recmod.setRemoteAccess(true);
					recmod.setUnitId(cnfModel.getUnitId());
					recmod.refresh();
					recordsDiagram = new RecordsDialog(recmod);
				} catch (Exception ex) {
					Main.showError("Chyba vstupních dat", "Nelze zobrazit záznamy");
					return;
				}
			}
			else {
				RecordsModel recmod = new RecordsModel();
				recmod.setRemoteAccess(false);
				recmod.refresh();					
				recordsDiagram = new RecordsDialog(recmod);
			}
		}

	}




	/**
	 * Watering configuration panel
	 * 
	 * @author Lukas Vavra
	 *
	 */
	public class WateringPanel extends JPanel {


		/**
		 * Panel constructor
		 * 
		 */
		public WateringPanel() {
			super(new GridBagLayout());

			setBorder(BorderFactory.createTitledBorder("Nastavení zavlažování"));

			GridBagConstraints cs = new GridBagConstraints();
			cs.insets = new Insets(10, 10, 10, 10);
			cs.anchor = GridBagConstraints.NORTH;
			cs.fill = GridBagConstraints.HORIZONTAL;
			cs.weightx = 1;

			wateringTimeListPanel = new TimeListPanel("Časy zavlažování", cnfModel.getWateringTimes(), ConfigModel.WAT_DELAY_UNITS, ConfigModel.WAT_DELAY_STEP);
			cs.gridx = 0;
			cs.gridy = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			this.add(wateringTimeListPanel, cs);

			JPanel optionPanel = new JPanel(new GridBagLayout());
			optionPanel.setBorder(BorderFactory.createTitledBorder("Automaticky"));
			cs.gridx = 1;
			cs.gridy = 0;
			cs.gridwidth = 1;
			cs.gridheight = 0;
			this.add(optionPanel, cs);

			// Option Panel
			cs.insets = new Insets(10, 5, 10, 5);

			autoWatCtrl = new JCheckBox("Zapnout");
			autoWatCtrl.addItemListener(new AutoctrlListener());
			cs.gridx = 0;
			cs.gridy = 0;
			cs.ipadx = 0;
			cs.gridwidth = GridBagConstraints.REMAINDER;
			cs.gridheight = 1;
			optionPanel.add(autoWatCtrl, cs);

			cs.gridx = 0;
			cs.gridy = 1;
			cs.ipadx = 0;
			cs.gridwidth = GridBagConstraints.REMAINDER;
			cs.gridheight = 1;
			optionPanel.add(soilText, cs);

			cs.gridx = 0;
			cs.gridy = 2;
			cs.ipadx = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(minPrefix, cs);

			minField = new JTextField(20);
			cs.gridx = 1;
			cs.gridy = 2;
			cs.ipadx = 15;
			cs.weightx = 1;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(minField, cs);
			if(cnfModel.isAutoWatering())
				minField.setText(Integer.toString(cnfModel.getMinSM()));

			cs.gridx = 2;
			cs.gridy = 2;
			cs.ipadx = 0;
			cs.weightx = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(minPostfix, cs);

			cs.gridx = 0;
			cs.gridy = 3;
			cs.ipadx = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(maxPrefix, cs);

			maxField = new JTextField(20);
			cs.gridx = 1;
			cs.gridy = 3;
			cs.ipadx = 15;
			cs.weightx = 1;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(maxField, cs);
			if(cnfModel.isAutoWatering())
				maxField.setText(Integer.toString(cnfModel.getMaxSM()));


			cs.gridx = 2;
			cs.gridy = 3;
			cs.ipadx = 0;
			cs.weightx = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(maxPostfix, cs);

			if(cnfModel.isAutoWatering())
				autoWatCtrl.setSelected(true);
			else {
				autoWatCtrl.setSelected(false);
				setAutoctrlEnabled(false);
			}

		}

		/**
		 * Set enabled flag for advanced options menu
		 * 
		 * @param enabled Enabled flag, true - enabled, false - disabled
		 */
		private void setAutoctrlEnabled(boolean enabled) {
			soilText.setEnabled(enabled);
			minPrefix.setEnabled(enabled);
			minField.setEnabled(enabled);
			minPostfix.setEnabled(enabled);
			maxPrefix.setEnabled(enabled);
			maxField.setEnabled(enabled);
			maxPostfix.setEnabled(enabled);
		}

		/**
		 * Advanced options checkbox listener
		 * 
		 * @author Lukas Vavra
		 *
		 */
		public class AutoctrlListener implements ItemListener {
			@Override
			public void itemStateChanged(ItemEvent e) {
				if(e.getStateChange() == ItemEvent.SELECTED) {
					setAutoctrlEnabled(true);
				}
				else {
					setAutoctrlEnabled(false);
				}
			}

		}

	}

	/**
	 * Ventilation configuration panel
	 * 
	 * @author Lukas Vavra
	 *
	 */
	public class VentilationPanel extends JPanel {

		/**
		 * Panel contructor
		 * 
		 */
		public VentilationPanel() {
			super(new GridBagLayout());

			setBorder(BorderFactory.createTitledBorder("Nastavení ventilace"));

			GridBagConstraints cs = new GridBagConstraints();
			cs.insets = new Insets(10, 10, 10, 10);
			cs.anchor = GridBagConstraints.NORTH;
			cs.fill = GridBagConstraints.HORIZONTAL;
			cs.weightx = 1;

			ventilationTimeListPanel = new TimeListPanel("Časy ventilace", cnfModel.getVentilationTimes(), ConfigModel.VENT_DELAY_UNITS, ConfigModel.VENT_DELAY_STEP);
			cs.gridx = 0;
			cs.gridy = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			this.add(ventilationTimeListPanel , cs);


			JPanel optionPanel = new JPanel(new GridBagLayout());
			optionPanel.setBorder(BorderFactory.createTitledBorder("Automaticky"));
			cs.gridx = 1;
			cs.gridy = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			this.add(optionPanel, cs);

			// Option Panel
			cs.insets = new Insets(10, 5, 10, 5);
			cs.weighty = 0;

			autoVentCtrl = new JCheckBox("Zapnout");
			autoVentCtrl.addItemListener(new AutoctrlListener());
			cs.gridx = 0;
			cs.gridy = 0;
			cs.ipadx = 0;
			cs.gridwidth = GridBagConstraints.REMAINDER;
			cs.gridheight = 1;
			optionPanel.add(autoVentCtrl, cs);

			cs.gridx = 0;
			cs.gridy = 1;
			cs.ipadx = 0;
			cs.gridwidth = GridBagConstraints.REMAINDER;
			cs.gridheight = 1;
			optionPanel.add(tempText, cs);

			cs.gridx = 0;
			cs.gridy = 2;
			cs.ipadx = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(maxTPrefix, cs);

			maxTField = new JTextField(20);
			cs.weightx = 1;
			cs.gridx = 1;
			cs.gridy = 2;
			cs.ipadx = 15;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(maxTField, cs);
			if(cnfModel.isAutoVentilation())
				maxTField.setText(Integer.toString(cnfModel.getMaxTemp()));

			cs.weightx = 0;
			cs.gridx = 2;
			cs.gridy = 2;
			cs.ipadx = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(maxTPostfix, cs);

			cs.gridx = 0;
			cs.gridy = 3;
			cs.ipadx = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(minTPrefix, cs);

			minTField = new JTextField(20);
			cs.gridx = 1;
			cs.gridy = 3;
			cs.ipadx = 15;
			cs.weightx = 1;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(minTField, cs);
			if(cnfModel.isAutoVentilation())
				minTField.setText(Integer.toString(cnfModel.getMinTemp()));


			cs.gridx = 2;
			cs.gridy = 3;
			cs.ipadx = 0;
			cs.weightx = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(minTPostfix, cs);

			cs.gridx = 0;
			cs.gridy = 4;
			cs.ipadx = 0;
			cs.weightx = 0;
			cs.gridwidth = GridBagConstraints.REMAINDER;
			cs.gridheight = 1;
			optionPanel.add(humText, cs);

			cs.gridx = 0;
			cs.gridy = 5;
			cs.ipadx = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(maxHPrefix, cs);

			maxHField = new JTextField(20);
			cs.gridx = 1;
			cs.gridy = 5;
			cs.ipadx = 15;
			cs.weightx = 1;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(maxHField, cs);
			if(cnfModel.isAutoVentilation())
				maxHField.setText(Integer.toString(cnfModel.getMaxHum()));


			cs.gridx = 2;
			cs.gridy = 5;
			cs.ipadx = 0;
			cs.weightx = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(maxHPostfix, cs);

			cs.gridx = 0;
			cs.gridy = 6;
			cs.ipadx = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(minHPrefix, cs);

			minHField = new JTextField(20);
			cs.gridx = 1;
			cs.gridy = 6;
			cs.ipadx = 15;
			cs.weightx = 1;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(minHField, cs);
			if(cnfModel.isAutoVentilation())
				minHField.setText(Integer.toString(cnfModel.getMinHum()));


			cs.gridx = 2;
			cs.gridy = 6;
			cs.ipadx = 0;
			cs.weightx = 0;
			cs.gridwidth = 1;
			cs.gridheight = 1;
			optionPanel.add(minHPostfix, cs);

			if(cnfModel.isAutoVentilation())
				autoVentCtrl.setSelected(true); 
			else {
				autoVentCtrl.setSelected(false);
				setAutoctrlEnabled(false);
			}
		}

		/**
		 * Set enabled flag for advanced options menu
		 * 
		 * @param enabled Enabled flag, true - enabled, false - disabled
		 */		
		private void setAutoctrlEnabled(boolean enabled) {
			tempText.setEnabled(enabled);
			humText.setEnabled(enabled);
			minTPrefix.setEnabled(enabled);
			minTField.setEnabled(enabled);
			minTPostfix.setEnabled(enabled);
			maxTPrefix.setEnabled(enabled);
			maxTField.setEnabled(enabled);
			maxTPostfix.setEnabled(enabled);
			minHPrefix.setEnabled(enabled);
			minHField.setEnabled(enabled);
			minHPostfix.setEnabled(enabled);
			maxHPrefix.setEnabled(enabled);
			maxHField.setEnabled(enabled);
			maxHPostfix.setEnabled(enabled);
		}

		/**
		 * Advanced options checkbox listener
		 * 
		 * @author Lukas Vavra
		 *
		 */
		public class AutoctrlListener implements ItemListener {
			@Override
			public void itemStateChanged(ItemEvent e) {
				if(e.getStateChange() == ItemEvent.SELECTED) {
					setAutoctrlEnabled(true);
				}
				else {
					setAutoctrlEnabled(false);
				}
			}

		}
	}

	/**
	 * Time panel for manage action times and delays
	 * 
	 * @author Lukas Vavra
	 *
	 */
	public class TimeListPanel extends JPanel {
		private JList<String> list;
		private DefaultListModel<String> model;

		JSpinner timeSpinner;
		JSpinner delaySpinner;

		/**
		 * Time list panel constructor
		 * 
		 * @param title Panel border title
		 * @param data Times array [HH:mm, ddds]
		 */
		public TimeListPanel(String title, String[] data, String delayUnits, int delayStep) {
			super(new GridBagLayout());
			setBorder(BorderFactory.createTitledBorder(title));

			model = new DefaultListModel<String>();
			if(data != null)
				for(String o : data) {
					if(o != null)
						model.addElement(o);
				}

			list = new JList<>(model);
			list.addKeyListener(new KeyDelete());
			JScrollPane scroll = new JScrollPane(list);
			scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

			GridBagConstraints cs = new GridBagConstraints();
			cs.insets = new Insets(10, 10, 10, 10);
			cs.fill = GridBagConstraints.BOTH;

			cs.gridx = 0;
			cs.gridy = 0;
			cs.weightx = 0;
			add(new JLabel("Čas spuštění: "), cs);

			timeSpinner = createTimeSpinner();
			cs.gridx = 0;
			cs.gridy = 1;
			cs.weightx = 1;
			add(timeSpinner, cs);

			cs.gridx = 0;
			cs.gridy = 2;
			cs.weightx = 0;
			add(new JLabel("Délka spuštění: "), cs);

			delaySpinner = createDelaySpinner(delayUnits, delayStep);
			cs.gridx = 0;
			cs.gridy = 3;
			cs.weightx = 1;
			add(delaySpinner, cs);

			JButton addit = new JButton("Přidat");
			addit.addActionListener(new AddItem());
			cs.gridx = 0;
			cs.gridy = 4;
			cs.gridwidth = 2;
			cs.weightx = 1;
			add(addit, cs);

			cs.gridx = 0;
			cs.gridy = 5;
			cs.gridwidth = 2;
			cs.weightx = 1;
			cs.weighty = 1;
			cs.ipady = 100;
			add(scroll, cs);

			JButton remove = new JButton("<html>Odebrat<br>označené</html>");
			remove.addActionListener(new RemoveItem());
			cs.gridx = 0;
			cs.gridy = 6;
			cs.gridwidth = 2;
			cs.weightx = 1;
			cs.weighty = 0;
			cs.ipady = 0;
			add(remove, cs);
		}

		/**
		 * Create JSpinner and spinner model for times
		 * 
		 * @return JSpinner with time values
		 */
		private JSpinner createTimeSpinner() {
			String[] time = new String[144];
			int i = 0;
			for(int h = 0; h < 24; h++)
				for(int m = 0; m < 60; m += 10) {
					time[i] = (h < 10 ? "0".concat(Integer.toString(h)) : Integer.toString(h))
							.concat(":").concat(m == 0 ? "00" : Integer.toString(m));
					i++;
				}

			SpinnerListModel spinmodel = new SpinnerListModel(time);
			JSpinner spinner = new JSpinner(spinmodel);
			return spinner;
		}

		/**
		 * Create JSpinner and model for delays
		 * 
		 * @return JSpinner with delay values
		 */
		private JSpinner createDelaySpinner(String delayUnits, int step) {
			String[] delay = new String[255];
			int i = 0;
			for(int d = step; d < (step * 255); d += step) {
				delay[i] = Integer.toString(d).concat(" ").concat(delayUnits);
				i++;
			}

			SpinnerListModel spinmodel = new SpinnerListModel(delay);
			JSpinner spinner = new JSpinner(spinmodel);
			return spinner;

		}

		/**
		 * Get data from list
		 * 
		 * @return Time strings array [HH:mm, ddds]
		 */
		public String[] getData() {			
			if(model != null) {
				String[] data = new String[model.getSize()];
				for(int i = 0; i < model.getSize(); i++) {
					data[i] = model.get(i);
				}
				return data;
			}	
			return null;
		}

		/**
		 * Add item button listener
		 * 
		 * @author Lukas Vavra
		 *
		 */
		private class AddItem implements ActionListener {
			@Override
			public void actionPerformed(ActionEvent e) {
				if(model.getSize() < 31) {					
					SimpleDateFormat dateParser = new SimpleDateFormat("HH:mm");
					String time = timeSpinner.getValue().toString();
					String element = time.concat(", ").concat(delaySpinner.getValue().toString());
					if(model.getSize() == 0) {
						model.addElement(element);
						return;
					}

					Date newTime;
					try {
						newTime = dateParser.parse(time);
					} catch (ParseException e1) {
						Main.showError("Chyba převodu", "Chybný formát času: ".concat(time));
						return;
					}

					Date listTime;
					int i;
					for(i = 0; i < model.getSize(); i++) {
						try {
							listTime = dateParser.parse(model.get(i).split(", ")[0]);
						} catch (ParseException e1) {
							Main.showError("Chyba převodu", "Chybný formát času: ".concat(model.get(i).split(", ")[0]));
							return;
						}

						if(newTime.compareTo(listTime) == 0) {
							Main.showError("Chybný čas", "Zadaný čas již v seznamu existuje");
							return;
						}
						else if (newTime.compareTo(listTime) < 0) {
							model.add(i, element);
							list.ensureIndexIsVisible(i);
							return;
						}
					}
					model.addElement(element);
					list.ensureIndexIsVisible(model.getSize() - 1);
				}
				else {
					Main.showInfo("Dosažen maximální počet časů");
				}

			}

		}

		/**
		 * Remove item button listener
		 * 
		 * @author Lukas Vavra
		 *
		 */
		private class RemoveItem implements ActionListener {
			@Override
			public void actionPerformed(ActionEvent e) {
				int index = list.getSelectedIndex();
				int lastIndex = model.getSize();

				while(index >= 0) {
					model.remove(index);
					lastIndex = index;
					index = list.getSelectedIndex();
				}
				if(lastIndex < model.getSize()) 
					list.setSelectedIndex(lastIndex);
			}

		}

		/**
		 * Keyboard listener
		 * 
		 * 'Delete' - remove item
		 * 
		 * @author Lukas Vavra
		 *
		 */
		private class KeyDelete implements KeyListener {
			@Override
			public void keyPressed(KeyEvent e) {
				if(e.getKeyCode() == KeyEvent.VK_DELETE) {
					int index = list.getSelectedIndex();
					int lastIndex = model.getSize();

					while(index >= 0) {
						model.remove(index);
						lastIndex = index;
						index = list.getSelectedIndex();
					}
					if(lastIndex < model.getSize()) 
						list.setSelectedIndex(lastIndex);
				}
			}

			@Override
			public void keyReleased(KeyEvent e) {}

			@Override
			public void keyTyped(KeyEvent e) {}
		}
	}
}
